package com.youpingou.util;

import com.github.wxpay.sdk.WXPay;
import com.youpingou.config.PayConfig;
import com.youpingou.service.OrderService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: XinQi.Yuan
 **/
@Component
public class PayHelper {
    /**
     * WXPay是微信支付的最重要的对象，其实他就是微信提供的工具类
     * 生成wxurl、支付、查看支付状态都通过WXPay这个对象完成
     */
    private WXPay wxPay;

    private static final Logger logger = LoggerFactory.getLogger(PayHelper.class);
    /**
     * 当我们生成wxurl之后，我们将这个url保存到redis中10分钟
     * 同一个订单号只能生成一个wxurl，当某一个订单已经生成了wxurl的时候，10分钟不会重复生成
     *
     *
     */
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 支付成功，修改订单状态
     */
    @Autowired
    private OrderService orderService;

    /**
     *
     * @param payConfig 刚刚准备的参数对象
     */
    public PayHelper(PayConfig payConfig) {
        // 真实开发时
        wxPay = new WXPay(payConfig);
        // 测试时
        // wxPay = new WXPay(payConfig, WXPayConstants.SignType.MD5, true);
    }

    /**
     * 创建支付url
     * @param sn
     * @return
     */
    public String createPayUrl(String sn) {
        /**
         * 存储到redis中的key
         */
        String key = "pay.url." + sn;
        try {
            String url = this.redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(url)) {
                return url;
            }
        } catch (Exception e) {
            logger.error("查询缓存付款链接异常,订单编号：{}", sn, e);
        }

        try {
            /**
             * 在map集合中，存放微信需要的必须参数
             */
            Map<String, String> data = new HashMap<>();
            // 商品描述：值随便填写 ***
            data.put("body", "优品购");
            // 订单号---是唯一编号，不可以随便写 ***
            data.put("out_trade_no", sn);
            //货币 ： 人民币，是微信定义好的
            data.put("fee_type", "CNY");
            //金额，单位是分  ***
            data.put("total_fee", "1");
            //调用微信支付的终端IP（商城的IP），ip地址随便写
            data.put("spbill_create_ip", "127.0.0.1");
            //回调地址：随便写
            data.put("notify_url", "https://3zp5818261.imdo.co/order-service/pay/callback");
            // 交易类型为扫码支付：固定
            data.put("trade_type", "NATIVE");
            //商品id,使用假数据：随便写
            data.put("product_id", "1234567");

            /**
             * unifiedOrder：去微信支付中生成订单，并返回支付url
             */
            Map<String, String> result = this.wxPay.unifiedOrder(data);

            if ("SUCCESS".equals(result.get("return_code"))) {
                String url = result.get("code_url");
                // 将付款地址缓存，时间为10分钟
                try {
                    this.redisTemplate.opsForValue().set(key, url, 10, TimeUnit.MINUTES);
                } catch (Exception e) {
                    logger.error("缓存付款链接异常,订单编号：{}", sn, e);
                }
                return url;
            } else {
                logger.error("创建预交易订单失败，错误信息：{}", result.get("return_msg"));
                return null;
            }
        } catch (Exception e) {
            logger.error("创建预交易订单异常", e);
            return null;
        }
    }

    /**
     * 查询订单状态
     *
     * @param sn
     * @return
     * 0 未支付
     * 1 支付成功
     * 2 付款失败
     */
    public Integer queryOrder(String sn) {
        Map<String, String> data = new HashMap<>();
        // 订单号
        data.put("out_trade_no", sn);
        try {
            Map<String, String> result = this.wxPay.orderQuery(data);
            if (result == null) {
                // 未查询到结果，认为是未付款
                return 0;
            }
            String state = result.get("trade_state");
            if ("SUCCESS".equals(state)) {
                // success，则认为付款成功

                // 修改订单状态
                this.orderService.updateStatus(sn, 1);
                return 1;
            } else if (StringUtils.equals("USERPAYING", state) || StringUtils.equals("NOTPAY", state)) {
                // 未付款或正在付款，都认为是未付款
                return 0;
            } else {
                // 其它状态认为是付款失败
                return 2;
            }
        } catch (Exception e) {
            logger.error("查询订单状态异常", e);
            return 0;
        }
    }
}